<template>
  <div class="home">
    <Card>
      <Row style="margin-bottom: 20px" @keydown.enter.native="getList">
        <Col span="12" style="display: flex; gap: 10px">
          <Input style="width: 300px" v-model="searchForm.description" placeholder="请输入文件描述" clearable></Input>
          <DatePicker type="daterange" placement="bottom-end" placeholder="请选择时间" style="width: 300px" @on-change="handleDate"></DatePicker>
        </Col>
        <Col span="12" style="display: flex; gap: 10px">
          <Button type="primary" @click="getList" ghost>搜索/刷新</Button>
          <Button @click="addVisible = true" type="success" icon="ios-cloud-upload-outline" ghost>文件上传</Button>
          <Button @click="deleteList" type="error" icon="ios-trash" ghost>批量删除</Button>
        </Col>
      </Row>
      <Table border :columns="columns" :data="tableData" @on-selection-change="showSelect" ref="table"></Table>
      <Row type="flex" justify="end" class="page">
        <Page
          :current="searchForm.current"
          :total="total"
          :page-size="searchForm.pageSize"
          @on-change="changePage"
          @on-page-size-change="changePageSize"
          :page-size-opts="[10, 20, 50]"
          size="small"
          show-total
          show-elevator
          show-sizer
        ></Page>
      </Row>
    </Card>

    <Drawer :closable="false" width="640" title="文件上传" v-model="addVisible" closable>
      <Form :model="formData">
        <Row :gutter="32">
          <FormItem label="类型" label-position="top" style="width: 95%; margin-left: 18px">
            <Select v-model="formData.type" placeholder="请选择类型">
              <Option value="图片">图片</Option>
              <Option value="文件">文件</Option>
              <Option value="Excel">Excel</Option>
            </Select>
          </FormItem>
        </Row>
        <FormItem label="文件描述" label-position="top">
          <Input type="textarea" v-model="formData.description" :rows="4" placeholder="请输入文件描述" />
        </FormItem>
        <FormItem>
          <div>
            <Upload multiple type="drag" :before-upload="handleUpload" :action="uploadApi">
              <div style="padding: 20px 0">
                <Icon type="ios-cloud-upload" size="52" style="color: #3399ff"></Icon>
                <p>点击这里文件上传或将文件拖拽到这里上传</p>
              </div>
            </Upload>
            <div v-if="uploadFile !== null">上传文件: {{ uploadFile.name }}</div>
          </div>
        </FormItem>
      </Form>
      <div class="drawer-footer">
        <Button style="margin-right: 8px" @click="clearFile" type="error">清空文件</Button>
        <Button type="primary" @click="doUploadFile" :loading="loadingUpload">确认上传</Button>
      </div>
    </Drawer>

    <Modal v-model="picVisible" title="图片预览" footer-hide draggable>
      <img :src="infoForm.url" alt="无效的图片链接" style="width: 100%; margin: 0 auto; display: block" />
    </Modal>
    <Update :id="currentRow.id" :visible="updateVisible" @close="updateVisible = false" />
  </div>
</template>

<script>
import { deleteFile, getListFileByPage, updateFile, uploadApi, uploadFile } from '@/api/file'
import { saveAs } from 'file-saver'
import Update from './Update'

export default {
  name: 'HomeView',
  components: {
    Update,
  },
  data() {
    return {
      searchForm: {},
      tableData: [],
      total: 0,
      picVisible: false, //图片预览
      infoForm: {}, //图片信息
      addVisible: false, //文件上传窗口
      // 文件上传表单
      formData: {
        type: '文件',
        description: '',
      },
      uploadFile: null,
      loadingUpload: false,
      currentRow: {},
      selectRows: [],
      updateVisible: false,
      uploadApi: uploadApi,
      columns: [
        {
          type: 'selection',
          width: 60,
          align: 'center',
          fixed: 'left',
        },
        {
          title: '文件',
          key: 'url',
          fixed: 'left',
          render: (h, params) => {
            if (params.row.type === '文件') {
              return h('a', {}, '文件')
            } else {
              return h('img', {
                attrs: {
                  src: params.row.url,
                  alt: '加载图片失败',
                },
                style: {
                  cursor: 'pointer',
                  width: '40px',
                  height: '40px',
                  'margin-top': '5px',
                  'object-fit': 'contain',
                },
                on: {
                  click: () => {
                    this.showPic(params.row)
                  },
                },
              })
            }
          },
        },
        {
          title: '大小',
          key: 'size',
          sortable: true,
        },
        {
          title: '分类',
          key: 'type',
          filters: [
            {
              label: '图片',
              value: '图片',
            },
            {
              label: '文件',
              value: '文件',
            },
          ],
          filterMethod(value, row) {
            if (value === '' || value === null) {
              return true
            }
            return row.type && row.type.indexOf(value) > -1
          },
        },
        {
          title: '描述',
          key: 'description',
          render: (h, params) => {
            const description = params.row.description
            const maxLength = 20

            //  只显示20个字符，多的点击显示
            return h(
              'a',
              {
                on: {
                  click: () => {
                    this.$copyText(description).then(() => {
                      this.$Message.success('复制描述成功')
                    })
                  },
                },
              },
              description.length > maxLength ? description.substring(0, maxLength) + '...' : description,
            )
          },
        },
        {
          title: '备注',
          key: 'remark',
          render: (h, params) => {
            const remark = params.row.remark
            const maxLength = 20

            //  只显示20个字符，多的点击显示
            return h(
              'span',
              {
                on: {
                  click: () => {
                    this.$Message.info(remark)
                    this.$copyText(remark).then(() => {})
                  },
                },
              },
              remark.length > maxLength ? remark.substring(0, maxLength) + '...' : remark,
            )
          },
        },
        {
          title: '排序',
          key: 'sortable',
          sortable: true,
          width: 100,
        },
        {
          title: '创建时间',
          key: 'createTime',
          sortable: true,
          width: 180,
        },
        {
          title: '操作',
          key: 'action',
          width: 300,
          align: 'center',
          fixed: 'right',
          render: (h, params) => {
            return h('div', [
              h(
                'a',
                {
                  style: {
                    marginRight: '5px',
                  },
                  on: {
                    click: () => {
                      this.download(params.row)
                    },
                  },
                },
                '下载',
              ),
              h(
                'a',
                {
                  style: {
                    marginRight: '5px',
                  },
                  on: {
                    click: () => {
                      this.copyUrl(params.row)
                    },
                  },
                },
                '复制链接',
              ),
              h(
                'Button',
                {
                  props: {
                    type: 'primary',
                    size: 'small',
                    ghost: true,
                  },
                  style: {
                    marginRight: '5px',
                  },
                  on: {
                    click: () => {
                      this.update(params.row)
                    },
                  },
                },
                '修改',
              ),
              h(
                'Button',
                {
                  props: {
                    type: 'error',
                    size: 'small',
                    ghost: true,
                  },
                  on: {
                    click: () => {
                      this.remove(params.row)
                    },
                  },
                },
                '删除',
              ),
            ])
          },
        },
      ],
    }
  },
  methods: {
    async getList() {
      const res = await getListFileByPage(this.searchForm)
      if (res.code === 0) {
        this.tableData = res.data.records
        this.total = res.data.total
      }
    },
    showPic(v) {
      this.infoForm.url = v.url
      this.picVisible = true
    },
    download(v) {
      // 用file-server实现下载文件v.url
      const fileUrl = v.url
      const suffix = fileUrl.substring(fileUrl.lastIndexOf('.'))

      const xhr = new XMLHttpRequest()
      xhr.open('GET', v.url, true)
      xhr.responseType = 'blob'

      xhr.onload = function () {
        if (xhr.status === 200) {
          // 时间戳.文件(可根据实际情况更改文件名)
          const fileName = v.description + new Date().getTime() + suffix
          saveAs(xhr.response, fileName)
        }
      }
      xhr.send()
    },
    handleUpload(file) {
      this.uploadFile = file
      return false
    },
    async doUploadFile() {
      this.loadingUpload = true
      try {
        const formData = new FormData()
        formData.append('uploadFile', this.uploadFile)
        formData.append('type', this.formData.type)
        formData.append('description', this.formData.description)

        const res = await uploadFile(formData)
        if (res.code === 0) {
          this.$Message.success('上传成功')
          this.uploadFile = null
          this.formData = {
            type: '文件',
            description: '',
          }
        } else {
          this.$Message.error('上传失败' + res.message)
        }
      } catch (error) {
        console.error(error)
      } finally {
        this.loadingUpload = false
        this.addVisible = false
        await this.getList()
      }
    },
    copyUrl(row) {
      this.$copyText(row.url).then(() => {
        this.$Message.success('复制成功')
      })
    },
    update(row) {
      // 创建当前行数据的一个深拷贝，防止直接修改原始数据
      this.currentRow = JSON.parse(JSON.stringify(row))
      this.updateVisible = true
    },
    async handleUpdate() {
      const res = await updateFile(this.currentRow)
      if (res.code === 0) {
        this.$Message.success('操作成功')
        this.$emit('close')
      } else {
        this.$Message.error('操作失败' + res.message)
      }
      this.updateVisible = false
    },
    handleDate(v) {
      // this.searchForm.createStart = v[0]
      // this.searchForm.createEnd = v[1]
      this.searchForm.createStart = this.$dayjs(v[0]).format('YYYY-MM-DD HH:mm:ss')
      this.searchForm.createEnd = this.$dayjs(v[1]).endOf('day').format('YYYY-MM-DD HH:mm:ss')
    },
    remove(row) {
      this.$Modal.confirm({
        title: '正在删除',
        content: '确定删除文件吗？',
        onOk: async () => {
          const res = await deleteFile({ id: row.id })
          if (res.code === 0) {
            this.$Message.success('删除成功')
            await this.getList()
          }
        },
      })
    },
    deleteList() {
      this.$Modal.confirm({
        title: '正在删除',
        content: '确定删除文件吗？',
        onOk: async () => {
          //  对象遍历删除this.selectRows
          let success = 0
          let fail = 0
          for (const item of this.selectRows) {
            const res = await deleteFile({ id: item.id })
            if (res.code === 0) {
              success++
            } else {
              fail++
            }
          }
          this.$Message.success('删除成功' + success + '条')
          console.log('删除失败' + fail + '条')
          await this.getList()
        },
      })
    },
    clearFile() {
      this.uploadFile = null
    },
    showSelect(v) {
      this.selectRows = v
    },
    changePage(v) {
      this.searchForm.current = v
      this.getList()
    },
    changePageSize(v) {
      this.searchForm.pageSize = v
      this.getList()
    },
  },
  mounted() {
    this.getList()
  },
}
</script>

<style>
.drawer-footer {
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
  border-top: 1px solid #e8e8e8;
  padding: 10px 16px;
  text-align: right;
  background: #fff;
}
</style>
